﻿// zxCheckProjectTreeCtrl.cpp: 实现文件
//

#include "stdafx.h"
#include "resource.h"
#include "zxCheckProjectTreeCtrl.h"

#define CK_PROJ_TREE_NODE_ROOT		0
#define CK_PROJ_TREE_NODE_DATA		1
#define CK_PROJ_TREE_NODE_CASE		2
#define CK_PROJ_TREE_NODE_SOURCE	6//3
#define CK_PROJ_TREE_NODE_FOLDER	4
#define CK_PROJ_TREE_NODE_GDB		5
#define CK_PROJ_TREE_NODE_DATASET	7//5
#define CK_PROJ_TREE_NODE_RASTER	7//5
#define CK_PROJ_TREE_NODE_BAND		8


// zxCheckProjectTreeCtrl

IMPLEMENT_DYNAMIC(zxCheckProjectTreeCtrl, CTreeCtrl)

zxCheckProjectTreeCtrl::zxCheckProjectTreeCtrl()
{
	m_pProject = NULL;
	m_hCase = NULL;
	m_hSource = NULL;
	m_hSelected = NULL;
}

zxCheckProjectTreeCtrl::~zxCheckProjectTreeCtrl()
{
	Cleanup();
}


BEGIN_MESSAGE_MAP(zxCheckProjectTreeCtrl, CTreeCtrl)
	ON_WM_CREATE()
	ON_WM_SIZE()
	ON_NOTIFY_REFLECT(NM_DBLCLK, &zxCheckProjectTreeCtrl::OnNMDblclk)
	ON_NOTIFY_REFLECT(NM_RCLICK, &zxCheckProjectTreeCtrl::OnNMRClick)
END_MESSAGE_MAP()



// zxCheckProjectTreeCtrl 消息处理程序


int zxCheckProjectTreeCtrl::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
	if (CTreeCtrl::OnCreate(lpCreateStruct) == -1)
		return -1;

	// TODO:  在此添加您专用的创建代码
	const DWORD dwViewStyle = WS_CHILD | WS_VISIBLE | TVS_HASLINES | /*TVS_LINESATROOT |*/ TVS_HASBUTTONS | WS_CLIPSIBLINGS | WS_CLIPCHILDREN /*| TVS_CHECKBOXES | TVS_NOSCROLL*/;

	this->ModifyStyle(0, dwViewStyle);
	AttachBitmap();

	InsertItem("检查工程", CK_PROJ_TREE_NODE_ROOT, CK_PROJ_TREE_NODE_ROOT);

	return 0;
}


void zxCheckProjectTreeCtrl::OnSize(UINT nType, int cx, int cy)
{
	CTreeCtrl::OnSize(nType, cx, cy);

	// TODO: 在此处添加消息处理程序代码
}


void zxCheckProjectTreeCtrl::AttachBitmap()
{
	CBitmap bmp;
	if (bmp.LoadBitmap(IDB_BITMAP_CHECK_PROJECT_TREE_24))
	{
		m_il.Create(24, 24, ILC_COLOR32 | ILC_MASK, 0, 0);
		m_il.Add(&bmp, RGB(255, 0, 255));
		int nCount = m_il.GetImageCount();
		for (int i = 1; i < nCount; i++)         //support 16
		{
			m_il.SetOverlayImage(i, i);
		}
		SetImageList(&m_il, TVSIL_NORMAL);
	}
}


void zxCheckProjectTreeCtrl::Clear()
{
	m_pProject = NULL;

	CleanupCases();
	CleanupDataSources();

	DeleteItem(m_hCase);
	DeleteItem(m_hSource);
	m_hCase = NULL;
	m_hSource = NULL;
}

void zxCheckProjectTreeCtrl::Cleanup()
{
	//CleanupCases();
	//CleanupDataSources();
}



void zxCheckProjectTreeCtrl::Populate(ck::CheckProject* pProject)
{
	m_pProject = pProject;

	//DeleteAllItems();
	Cleanup();

	SetProjectName();

	PopulateCheckCase();
	PopulateDataSource();

	Expand(GetRootItem(), TVE_EXPAND);
}

RESULTCODE	zxCheckProjectTreeCtrl::AddDataSource(ck::DataSource* pDataSource)
{
	if (pDataSource == NULL)
	{
		return RC_FAILURE;
	}

	int nIcon = GetDataSourceNodeIcon(pDataSource);

	const char* szSourceName = pDataSource->GetName();
	HTREEITEM hItem = InsertItem(szSourceName, nIcon, nIcon, m_hSource);
	if (hItem)
	{
		SetItemData(hItem, (DWORD_PTR)pDataSource);
		pDataSource->AddRef();

		//if (pDataSource->IsOpen())
		{
			PopulateDataSourceNode(hItem, pDataSource);
		}

		Expand(hItem, TVE_EXPAND);
		Expand(m_hSource, TVE_EXPAND);
	}

	return RC_SUCCESS;

	return RC_SUCCESS;
}

RESULTCODE zxCheckProjectTreeCtrl::AddDataProduct(ck::product::DataProduct* pProduct)
{
	return RC_SUCCESS;
}

int zxCheckProjectTreeCtrl::GetDataSourceNodeIcon(ck::DataSource* pDataSource)
{
	int nIcon = CK_PROJ_TREE_NODE_SOURCE;

	ck::ckDataSourceType type = pDataSource->GetType();
	switch (type)
	{
	case ck::ckFileDataSource:
	{
		nIcon = CK_PROJ_TREE_NODE_DATASET;
		ck::ckDataProductType productType = m_pProject->GetProductType();
		switch (productType)
		{
		case ck::ckDptUnknown:
			break;
		case ck::ckDptLandCover30:
			break;
		case ck::ckDptLandCover10:
			break;
		case ck::ckDptLandsat05:
			nIcon = CK_PROJ_TREE_NODE_RASTER;
			break;
		case ck::ckDptLandsat08:
			break;
		default:
			break;
		}
	}
	break;
	case ck::ckFolderDataSource:
		nIcon = CK_PROJ_TREE_NODE_SOURCE;
		break;
	case ck::ckGDBDataSource:
		nIcon = CK_PROJ_TREE_NODE_GDB;
	}

	return nIcon;
}

void zxCheckProjectTreeCtrl::PopulateDataSourceNode(HTREEITEM hSourceItem, ck::DataSource* pDataSource)
{
	ck::ckDataSourceType type = pDataSource->GetType();
	switch (type)
	{
	case ck::ckFileDataSource:
		PopulateDataSourceNode(hSourceItem, (ck::FileDataSource*)pDataSource);
		break;
	case ck::ckFolderDataSource:
		PopulateDataSourceNode(hSourceItem, (ck::FolderDataSource*)pDataSource);
		break;
	case ck::ckGDBDataSource:
		break;
	}
}

void zxCheckProjectTreeCtrl::PopulateDataSourceNode(HTREEITEM hSourceItem, ck::FileDataSource* pDataSource)
{

	{	//添加本级文件夹下的所有数据集
		ck::data::Dataset* pDataset = NULL;
		ck::ckDataProductType type = m_pProject->GetProductType();

		pDataset = pDataSource->GetDataset(type);
		if (pDataset == NULL)
		{
			return;
		}
	}
}

void zxCheckProjectTreeCtrl::PopulateDataSourceNode(HTREEITEM hSourceItem, ck::FolderDataSource* pDataSource)
{

	//////////////////////////////////////////////////////////////////////////
	{	//添加本级文件夹下的所有数据集
		ck::data::Dataset* pDataset = NULL;
		ck::data::EnumDataset* pDatasets = NULL;
		ck::ckDataProductType type = m_pProject->GetProductType();

		pDatasets = pDataSource->GetDatasets(type);
		pDatasets->Reset();
		while ((pDataset = pDatasets->Next()))
		{
			const char* szDatasetName = pDataset->GetName();
			HTREEITEM hDatasetItem = InsertItem(szDatasetName, CK_PROJ_TREE_NODE_DATASET, CK_PROJ_TREE_NODE_DATASET, hSourceItem);
			if (hDatasetItem)
			{
				SetItemData(hDatasetItem, (DWORD_PTR)pDataset);
				pDataset->AddRef();
			}
		}
		pDatasets->Release();

	}
	//////////////////////////////////////////////////////////////////////////
	//{	//添加下一级文件夹
	//	ck::Folder* pFolder = NULL;
	//	ck::EnumFolder* pSubFolders = NULL;

	//	pSubFolders = pDataSource->GetSubFolders();
	//	pSubFolders->Reset();
	//	while ((pFolder = pSubFolders->Next()))
	//	{
	//		const char* szFolderName = pFolder->GetName();
	//		HTREEITEM hFolterItem = InsertItem(szFolderName, CK_PROJ_TREE_NODE_FOLDER, CK_PROJ_TREE_NODE_FOLDER, hSourceItem);

	//	}
	//	pSubFolders->Release();
	//}

	//////////////////////////////////////////////////////////////////////////

	Expand(hSourceItem, TVE_EXPAND);
}

void zxCheckProjectTreeCtrl::SetProjectName()
{
	const char* szName = m_pProject->GetName();
	HTREEITEM  hRoot = GetRootItem();
	SetItemText(hRoot, szName);
}


void zxCheckProjectTreeCtrl::PopulateCheckCase()
{
	HTREEITEM hRoot = GetRootItem();
	ck::CheckCase* pCase = m_pProject->GetCheckCase();
	if (!m_hCase)
	{
		m_hCase = InsertItem("检查方案", CK_PROJ_TREE_NODE_DATA, CK_PROJ_TREE_NODE_DATA, hRoot);
	}

	if (pCase)
	{
		InsertItem(pCase->GetName(), CK_PROJ_TREE_NODE_CASE, CK_PROJ_TREE_NODE_CASE, m_hCase);
	}
	Expand(m_hCase, TVE_EXPAND);
}

void zxCheckProjectTreeCtrl::PopulateDataSource()
{
	HTREEITEM hRoot = GetRootItem();
	if (!m_hSource)
	{
		m_hSource = InsertItem("检查数据", CK_PROJ_TREE_NODE_DATA, CK_PROJ_TREE_NODE_DATA, hRoot);
	}


	ck::DataSource* pSource = NULL;
	ck::EnumDataSource* pSources = m_pProject->GetDataSources();

	pSources->Reset();
	while ((pSource = pSources->Next()))
	{
		AddDataSource(pSource);
	}

	pSources->Release();

}

void zxCheckProjectTreeCtrl::OnNMDblclk(NMHDR *pNMHDR, LRESULT *pResult)
{
	// TODO: 在此添加控件通知处理程序代码
	*pResult = 0;

	if (!m_pProject)
	{
		return;
	}

	CPoint pt, spt;
	if (!GetCursorPos(&pt))
	{
		return;
	}
	spt = pt;
	ScreenToClient(&pt);
	UINT uFlag = 0;
	HTREEITEM hItem = HitTest(pt, &uFlag);
	if ((NULL == hItem) || !(TVHT_ONITEM&uFlag))
	{
		return;
	}
	SelectItem(hItem);
	m_hSelected = hItem;

	int nType = GetNodeType(hItem);
	switch (nType)
	{
	case PROJECT_TREE_ROOT_NODE:
		break;
	case PROJECT_TREE_CASE_ROOT_NODE:
		break;
	case PROJECT_TREE_CASE_NODE:
		break;
	case PROJECT_TREE_SOURCE_ROOT_NODE:
		break;
	case PROJECT_TREE_SOURCE_NODE:
	{
		HTREEITEM hDataSourceItem = hItem;

		ck::DataSource* pDataSource = (ck::DataSource*)GetItemData(hItem);
		if (pDataSource != NULL)
		{
			ck::ckDataSourceType type = pDataSource->GetType();
			switch (type)
			{
			case ck::ckFileDataSource:
			{
				ck::data::Dataset* pDataset = NULL;
				ck::FileDataSource* pFileDataSource = static_cast<ck::FileDataSource*>(pDataSource);
				pDataset = pFileDataSource->GetDataset(m_pProject->GetProductType());
				if (pDataset)
				{
					CleanupDatasetNode(hDataSourceItem);
					PopulateDatasetNode(hDataSourceItem, pDataset);
					pDataset->Release();
				}
			}
			break;
			//case ck::ckFolderDataSource:
			//	break;
			//case ck::ckGDBDataSource:
			//	break;
			default:
			{
				CleanupDataSourceNode(hDataSourceItem);
				PopulateDataSourceNode(hDataSourceItem, pDataSource);
			}
			break;
			}

		}
	}
	break;
	case PROJECT_TREE_DATASET_NODE:
	{
		if (!GetChildItem(hItem))
		{
			HTREEITEM hDatasetItem = hItem;
			ck::data::Dataset* pDataset = NULL;
			pDataset = (ck::data::Dataset*)GetItemData(hDatasetItem);

			CleanupDatasetNode(hDatasetItem);
			PopulateDatasetNode(hDatasetItem, pDataset);


			//

			//ck::ckDatasetType datasetType = pDataset->GetType();
			//switch (datasetType)
			//{
			//case ck::ckDstRaster:
			//	ck::data::RasterDataset* pRasterDataset = (ck::data::RasterDataset*)pDataset;
			//	PopulateRaterBandNode(hDatasetItem, pRasterDataset);
			//	break;
			//}
			////PopulateDatasetNode(hDataSourceItem, pDataSource);
		}
	}
	break;
	}

	//Expand(hItem, TVE_EXPAND);
}


int	zxCheckProjectTreeCtrl::GetNodeType(HTREEITEM hItem)
{
	int nType = PROJECT_TREE_ROOT_NODE;
	HTREEITEM hRoot = GetRootItem();
	if (hItem == hRoot)
	{
		return PROJECT_TREE_ROOT_NODE;
	}
	else if (hItem == m_hCase)
	{
		return PROJECT_TREE_CASE_ROOT_NODE;
	}
	else if (hItem == m_hSource)
	{
		return PROJECT_TREE_SOURCE_ROOT_NODE;
	}
	else if (GetParentItem(hItem) == m_hCase)
	{
		return PROJECT_TREE_CASE_NODE;
	}
	else if (GetParentItem(hItem) == m_hSource)
	{
		return PROJECT_TREE_SOURCE_NODE;
	}
	else if (GetParentItem(GetParentItem(hItem)) == m_hSource)
	{
		return PROJECT_TREE_DATASET_NODE;
	}
	else if (GetParentItem(GetParentItem(GetParentItem(hItem))) == m_hSource)
	{
		return PROJECT_TREE_BAND_NODE;
	}

	return nType;
}


void zxCheckProjectTreeCtrl::CleanupDatasetNode(HTREEITEM hDataSetItem)
{
	ck::data::Dataset* pDataset = NULL;
	pDataset = (ck::data::Dataset*)GetItemData(hDataSetItem);
	CleanupDatasetNode(hDataSetItem, pDataset);
}


void zxCheckProjectTreeCtrl::CleanupDatasetNode(HTREEITEM hDataSetItem, ck::data::Dataset* pDataset)
{
	ck::ckDatasetType dataSetType = pDataset->GetType();

	//清空DataSource下面的Dataset节点
	HTREEITEM hItem, hSibling;
	hItem = GetChildItem(hDataSetItem);
	while (hItem)
	{
		switch (dataSetType)
		{
		case ck::ckDstRaster:
			CleanupRasterBandNode(hItem);
			break;
		case ck::ckDstVector:
			break;
		}

		hSibling = this->GetNextSiblingItem(hItem);
		this->DeleteItem(hItem);
		hItem = hSibling;
	}
}

void zxCheckProjectTreeCtrl::CleanupRasterBandNode(HTREEITEM hItem)
{
	if (!hItem)
	{
		return;
	}

	ck::data::RasterBand* pBand = (ck::data::RasterBand*)GetItemData(hItem);
	if (pBand)
	{
		pBand->Release();
		pBand = NULL;
	}

}


void zxCheckProjectTreeCtrl::PopulateDatasetNode(HTREEITEM hDatasetItem, ck::data::Dataset* pDataset)
{
	ck::ckDatasetType dsType = pDataset->GetType();
	switch (dsType)
	{
	case ck::ckDstVector:
	{

	}
	break;
	case ck::ckDstRaster:
	{
		PopulateRaterBandNode(hDatasetItem, static_cast<ck::data::RasterDataset*>(pDataset));
	}
	break;
	default:
		break;
	}
}

void zxCheckProjectTreeCtrl::PopulateRaterBandNode(HTREEITEM hDatasetItem, ck::data::RasterDataset* pRasterDataset)
{
	ck::data::RasterBand* pBand = NULL;
	ck::data::EnumRasterBand* pBands = NULL;

	if (!pRasterDataset->IsOpen())
	{
		RESULTCODE rc;
		rc = pRasterDataset->Open();
		if (rc != RC_SUCCESS)
		{
			return;
		}
	}

	pBands = pRasterDataset->GetBands();
	pBands->Reset();
	while ((pBand = pBands->Next()))
	{
		HTREEITEM hItem = InsertItem(pBand->GetName(), CK_PROJ_TREE_NODE_BAND, CK_PROJ_TREE_NODE_BAND, hDatasetItem);
		SetItemData(hItem, (DWORD_PTR)pBand);
		pBand->AddRef();
	}

	pBands->Release();
}

void zxCheckProjectTreeCtrl::CleanupDataSourceNode(HTREEITEM hDataSourceItem)
{
	ck::DataSource* pDataSource = NULL;
	pDataSource = (ck::DataSource*)GetItemData(hDataSourceItem);

	ck::ckDataSourceType type = pDataSource->GetType();

	switch (type)
	{
	case ck::ckFileDataSource:
	{
		ck::data::Dataset* pDataset = NULL;
		ck::FileDataSource* pFileSource = static_cast<ck::FileDataSource*>(pDataSource);
		pDataset = pFileSource->GetDataset(m_pProject->GetProductType());

		RemoveDatasetNode(hDataSourceItem, pDataset);
	}
	break;
	//case ck::ckFolderDataSource:
	//	break;
	//case ck::ckGDBDataSource:
	//	break;
	default:
	{
		//清空DataSource下面的Dataset节点
		HTREEITEM hDatasetItem, hSibling;
		hDatasetItem = GetChildItem(hDataSourceItem);
		while (hDatasetItem)
		{
			ck::data::Dataset* pDataset = (ck::data::Dataset*)GetItemData(hDatasetItem);
			hSibling = this->GetNextSiblingItem(hDatasetItem);

			RemoveDatasetNode(hDatasetItem, pDataset);

			this->DeleteItem(hDatasetItem);
			hDatasetItem = hSibling;
		}
	}
	break;
	}
}

void zxCheckProjectTreeCtrl::RemoveDataSourceNode(HTREEITEM hDataSourceItem)
{
	if (!hDataSourceItem)
	{
		return;
	}

	ck::DataSource* pDataSource = NULL;
	pDataSource = (ck::DataSource*)GetItemData(hDataSourceItem);

	CleanupDataSourceNode(hDataSourceItem);

	DeleteItem(hDataSourceItem);
	if (pDataSource)
	{
		pDataSource->Release();
		pDataSource = NULL;
	}
}

void zxCheckProjectTreeCtrl::RemoveDatasetNode(HTREEITEM hDataSetItem, ck::data::Dataset* pDataset)
{
	if (!hDataSetItem)
	{
		return;
	}

	CleanupDatasetNode(hDataSetItem, pDataset);

	DeleteItem(hDataSetItem);

	if (pDataset)
	{
		pDataset->Release();
		pDataset = NULL;
	}
}

void zxCheckProjectTreeCtrl::CleanupCases()
{
	if (!m_hCase)
	{
		return;
	}
	HTREEITEM hItem, hSibling;
	hItem = GetChildItem(m_hCase);
	while (hItem)
	{
		hSibling = this->GetNextSiblingItem(hItem);
		this->DeleteItem(hItem);
		hItem = hSibling;
	}
}

void zxCheckProjectTreeCtrl::CleanupDataSources()
{
	if (!m_hSource)
	{
		return;
	}

	HTREEITEM hDataSourceItem, hSibling;
	hDataSourceItem = GetChildItem(m_hSource);
	while (hDataSourceItem)
	{
		RemoveDataSourceNode(hDataSourceItem);

		hSibling = this->GetNextSiblingItem(hDataSourceItem);
		this->DeleteItem(hDataSourceItem);
		hDataSourceItem = hSibling;
	}
}

void zxCheckProjectTreeCtrl::OnNMRClick(NMHDR *pNMHDR, LRESULT *pResult)
{
	// TODO: 在此添加控件通知处理程序代码
	*pResult = 0;

}
